﻿<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>PostMessage / SendMessage</title>
<meta name="description" content="Send messages to a window with this free macro program. PostMessage puts a message in the window's message queue, but SendMessage waits for a reply.">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="../css/commands.css" rel="stylesheet" type="text/css">
<link href="../css/print.css" rel="stylesheet" type="text/css" media="print">
</head>
<body>

<h1>PostMessage / SendMessage</h1>

<p>发送一条消息给一个窗口或一个控件 (SendMessage 还会等待回应)。</p>

<p class="CommandSyntax">PostMessage, Msg [, wParam, lParam, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]<br>
      SendMessage, Msg [, wParam, lParam, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]</p>
<h3>参数 </h3>
<table border="1" width="100%" cellspacing="0" cellpadding="3" bordercolor="#C0C0C0">
  <tr>
    <td>Msg</td>
    <td>需要发送的消息码，可以是一个 <a href="../Variables.htm#Expressions"> 表达式</a>。参看 <a href="../misc/SendMessageList.htm">消息列表</a> 以确定数值。</td>
  </tr>
  <tr>
    <td>wParam</td>
    <td>消息的第一个参数，可以是一个 <a href="../Variables.htm#Expressions">表达式</a>。如果为空或省略，将会发送 0。</td>
  </tr>
  <tr>
    <td>lParam</td>
    <td>消息的第二个参数，可以是一个 <a href="../Variables.htm#Expressions">表达式</a>。如果为空或省略，将会发送 0。</td>
  </tr>
  <tr>
    <td>Control</td>
    <td><p>如果此参数为空或省略，消息将被直接发送给目标窗口，而不是它的某个控件。否则，这个参数可以是 ClassNN (控件的类名和实例号) 或者控件的 名字/文本，两者都可通过 Window Spy 来确定。使用 名字/文本 时，匹配模式由 <a href="SetTitleMatchMode.htm">SetTitleMatchMode</a> 决定。</p>
    <p> 若要通过控件的 HWND (窗口句柄) 来操作，则将 <em>Control </em>参数留空并为 <em>WinTitle</em> 参数指定 <em>ahk_id %ControlHwnd%</em>  (也适用于隐藏控件，即使 <a href="DetectHiddenWindows.htm">DetectHiddenWindows</a> 为 Off)。一个控件的 HWND 通常可以通过 <a href="ControlGet.htm#Hwnd">ControlGet Hwnd</a>, <a href="MouseGetPos.htm">MouseGetPos</a>, 或 <a href="DllCall.htm">DllCall</a> 来获取。</p>
    </td>
  </tr>
  <tr>
    <td width="15%">WinTitle</td>
    <td width="85%">目标窗口的部分或整个标题 (匹配模式由 <a href="SetTitleMatchMode.htm">SetTitleMatchMode</a> 决定)。如果省略这个和另外3个参数，将使用 <a href="../LastFoundWindow.htm">上一次匹配窗口</a> 。如果这个参数为字母 A 且省略其他3个参数，将使用当前激活的窗口。要使用窗口类，指定 ahk_class 精确的类名 (Window Spy可以显示类名)。要使用 <a href="Process.htm">进程标识符 (PID)</a>，指定 ahk_pid %PID变量%。要使用 <a href="GroupAdd.htm">窗口组</a>，指定 ahk_group 组名。要使用窗口的 <a href="WinGet.htm">唯一ID</a>，指定 ahk_id %ID变量% (也接受 <a href="ControlGet.htm#Hwnd">控件的 HWND</a>)。要减小检测范围，使用指定 <a href="../LastFoundWindow.htm#multi">多重条件</a>。例如：<EM>My File.txt ahk_class Notepad</EM></td>
  </tr>
  <tr>
    <td>WinText</td>
    <td>如果使用这个参数，则它应该是目标窗口中某个文本元素的子字符串（在 Window Spy 中会显示出窗口中的文本元素）。隐藏文本只有在 <A href="DetectHiddenText.htm">DetectHiddenText</A> 设置为 ON 的时候才能检测到。</td>
  </tr>
  <tr>
    <td>ExcludeTitle</td>
    <td>标题含有此参数值的窗口将不被考虑。</td>
  </tr>
  <tr>
    <td>ExcludeText</td>
    <td>文本含有此参数值的窗口将不被考虑。</td>
  </tr>
</table>

<h3>ErrorLevel</h3>
<p>PostMessage: 如果出现问题，例如目标窗口或控件不存在， <a href="../misc/ErrorLevel.htm">ErrorLevel</a> 会被设为 1。否则为 0。</p>
<p>SendMessage: 如果出现问题，<a href="../misc/ErrorLevel.htm">ErrorLevel</a> 会被设为单词 FAIL。否则，会被设为此消息的数值结果，有时可能是一个根据消息的类型和消息的目标窗口的类型而决定的一个&ldquo;回覆 (reply) &rdquo;。这个结果是一个 0 与 4294967295
之间的整数。如果结果应该是有符号的，下列例子可以将负数结果展现出来：<em>MsgReply := ErrorLevel &gt; 0x7FFFFFFF ? -(~ErrorLevel) - 1 : ErrorLevel</em></p>
<h3>注意</h3>
<p>应该小心使用这些命令。因为发送一条消息到错误的窗口（或发送无效的消息）可能导致不可预料的行为，甚至使目标应用程序崩溃。这是因为多数应用程序在设计时并不会考虑对某些从外部来源发来的消息做处理。</p>
<p>PostMessage 将消息放置到与目标窗口相关的消息队列中。它不会等待回应或答覆。相比之下，SendMessage 会用最多5秒钟来等待目标窗口处理此消息。如果消息在这段时间内未处理完，此命令结束并设置 ErrorLevel 为单词 FAIL 。</p>
<p>参数 <em>Msg</em>, <em>wParam</em>, 与 <em>lParam</em> 都应该是 -2147483648 与 4294967295 (0xFFFFFFFF) 之间的整数。AutoHotkey 中所有的整型数值，都可以附加前缀 0x 来代表一个十六进制值。例如， 0xFF 等于 255 。</p>
<p>若要通过 <em>wParam</em> 或 <em>lParam</em> 发送一个字符串，可以指定一个变量的地址。以下例子使用 <a href="../Variables.htm#amp">取地址运算符 (&amp;)</a> 来完成此事：</p>
<pre>SendMessage, 0xC, 0, <strong>&amp;MyVar</strong>, ClassNN, WinTitle  <em>; 0XC 是 WM_SETTEXT</em></pre>
<p>在 v1.0.43.06 及以后的版本中，消息的接收者放置在 MyVar 中的字符串可以被正确辨认，无需附加步骤。不过这只有在参数的第一个字符是一个 与符号(&amp;) 时才可以。例如， <em>5+&amp;MyVar</em> 不行但是 <em>&amp;MyVar</em> 或 <em>&amp;MyVar+5</em> 就可以。</p>
<p>一个 带引号/原意(quoted/literal) 的字符串也可以被发送。参照以下的可用范例（此种情况下不应该使用 &amp; 操作符）：</p>
<pre>Run Notepad
WinWait 无标题 - 记事本
SendMessage, 0xC, 0, <strong>&quot;新的记事本标题&quot;</strong>  <em>; 0XC 是 WM_SETTEXT</em></pre>
<p>要发送一条消息给系统中所有的窗口（包括隐藏或无效的），指定 <em>WinTitle</em> 为 <em>ahk_id 0xFFFF</em> （0xFFFF 是 HWND_BROADCAST）。此技巧应该只在专门用于广播的消息上使用。例如以下的范例：</p>
<pre>SendMessage, 0x1A,,,, ahk_id 0xFFFF  <em>; 0x1A 是 WM_SETTINGCHANGE</em></pre>
<p>若想拥有能够接收消息的脚本，可以使用 <a href="OnMessage.htm">OnMessage()</a> 。</p>
<p>参看 <a href="../misc/SendMessage.htm">消息指南</a> 以获得使用这些命令的说明。</p>
<p>窗口标题与文本都是区分大小写的。隐藏窗口不会被检测，除非开启了 <a href="DetectHiddenWindows.htm">DetectHiddenWindows</a> 。</p>

<h3>相关命令</h3>
<p><a href="../misc/SendMessageList.htm">消息列表</a>, <a href="../misc/SendMessage.htm">消息指南</a>, <a href="OnMessage.htm">OnMessage()</a>, <a href="../misc/Winamp.htm">自动化 Winamp</a>, <a href="DllCall.htm">DllCall</a>, <a href="ControlSend.htm">ControlSend</a>, <a href="WinMenuSelectItem.htm">WinMenuSelectItem</a></p>
<h3>示例</h3>
<pre class="NoIndent">#o::  <em>; Win+O 热键关闭显示器。</em>
Sleep 1000  <em>; 给用户释放按键的机会（万一它们被释放会再次唤醒显示器）。</em>
<em>; 关闭显示器:</em>
SendMessage, 0x112, 0xF170, 2,, Program Manager  <em>; 0x112 是 WM_SYSCOMMAND, 0xF170 是 SC_MONITORPOWER。</em>
<em>; 上面的备注: 使用 -1 代替 2 可以打开显示器。</em>
<em>; 使用 1 代替 2 可以开启显示器的节能模式。</em>
return

<em>; 启动用户选择的屏幕保护程序：</em>
SendMessage, 0x112, 0xF140, 0,, Program Manager  <em>; 0x112 是 WM_SYSCOMMAND, 0xF140 是 SC_SCREENSAVE。</em>

<em>; 向上滚动一行 (用于拥有垂直滚动条的控件)：</em>
ControlGetFocus, control, A
SendMessage, 0x115, 0, 0, %control%, A

<em>; 向下滚动一行：</em>
ControlGetFocus, control, A
SendMessage, 0x115, 1, 0, %control%, A

<em>; 切换活动窗口的 键盘布局/语言 到英语：</em>
PostMessage, 0x50, 0, 0x4090409,, A  <em>; 0x50 是 WM_INPUTLANGCHANGEREQUEST。</em>

<em>; 本示例询问 Winamp 当前活动的音轨号是哪一个：</em>
SetTitleMatchMode, 2
SendMessage, 1024, 0, 120, - Winamp
if ErrorLevel &lt;&gt; FAIL
{
    ErrorLevel++  <em>; Winamp 的计数器从 &quot;0&quot; 开始，所以用 1 调整。</em>
    MsgBox, 音轨 #%ErrorLevel% 是活动的或正在播放。.
}
<em>; 参看 <a href="../misc/Winamp.htm">自动化 Winamp</a> 获得更多信息。</em>

<em>; 要查找一个 AHK脚本 的进程ID (另一个办法是 &quot;<a href="WinGet.htm">WinGet PID</a>&quot;):</em>
SetTitleMatchMode, 2
DetectHiddenWindows, on
SendMessage, 0x44, 0x405, 0, , SomeOtherScript.ahk - AutoHotkey v
MsgBox %ErrorLevel% 是进程 id。</pre></font>

</body>
</html>

